﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using WJP.Utils;

namespace WJP.ObjectModel
{
    /// <summary>
    /// 一个可进行简单属性扩展的类型
    /// </summary>
    [DataContract]
    [Serializable]
    public abstract class Extendable : IExtendable
    {
        /// <summary>
        /// 所有扩展的属性
        /// </summary>
        [DataMember]
        [Browsable(false)]
        private Dictionary<string, object> ExtendedProperties { get; set; }

        /// <summary>
        /// 返回当前已经扩展的属性个数
        /// </summary>
        [Browsable(false)]
        public int ExtenedPropertiesCount
        {
            get
            {
                if (ExtendedProperties == null)
                    return 0;
                return ExtendedProperties.Count;
            }
        }

        /// <summary>
        /// 用于扩展的属性列表
        /// <para>注意，如果设置 null 值，则表示清空该属性</para>
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        public object this[string property]
        {
            get
            {
                object obj = null;
                if (ExtendedProperties != null)
                    ExtendedProperties.TryGetValue(property, out obj);
                return obj;
            }
            set
            {
                OnExtendedPropertyChanging(property, value);
                if (value == null)
                {
                    if (ExtendedProperties != null)
                    {
                        ExtendedProperties.Remove(property);
                    }
                }
                else
                {
                    if (ExtendedProperties == null)
                        ExtendedProperties = new Dictionary<string, object>();
                    ExtendedProperties[property] = value;
                }
                OnExtendedPropertyChanged(property);
            }
        }

        /// <summary>
        /// 获取指定名称的扩展属性值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public T GetPropertyOrDefault<T>(string property, T defaultValue = null) where T : class
        {
            if (ExtendedProperties != null && ExtendedProperties.TryGetValue(property, out object obj))
                return (T)TypeHelper.CoerceValue(typeof(T), obj);
            return defaultValue;
        }

        /// <summary>
        /// 设置某个扩展属性为指定的值。
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        public void SetExtendedProperty(string property, object value)
        {
            this[property] = value;
        }

        /// <summary>
        /// 设置某个扩展属性为指定的值
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        public void SetExtendedProperty(string property, bool value)
        {
            this[property] = value.Box();
        }

        /// <summary>
        /// 获取已经设置的所有的扩展属性
        /// </summary>
        /// <returns></returns>
        public IEnumerable<KeyValuePair<string, object>> GetExtendedProperties()
        {
            if (ExtendedProperties != null)
                return ExtendedProperties;
            return Enumerable.Empty<KeyValuePair<string, object>>();
        }

        /// <summary>
        /// 扩展属性变更前事件
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        protected virtual void OnExtendedPropertyChanging(string property, object value)
        {
        }

        /// <summary>
        /// 扩展属性变更后事件
        /// </summary>
        /// <param name="property"></param>
        protected virtual void OnExtendedPropertyChanged(string property)
        {
        }
    }
}